﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Configuration;

namespace DLV.Library.Utilities
{
    public class ImageUpload
    {
        private const string ImageExtension = ".jpg";
        private readonly static string StaticUrl = WebConfigurationManager.AppSettings["StaticUrl"];
        private readonly static string PathLogo = WebConfigurationManager.AppSettings["PathLogo"].ToLower();

        public static string GetImageUrl(int size, string imagePath, bool waterMark, string text)
        {
            try
            {
                var fileName = Path.GetFileName(imagePath); //Tên hình ảnh gốc
                var fileNameScale = size + "_" + fileName.Replace(ImageExtension, ""); //Tên hình ảnh sau khi resize

                //Đường dẫn thư mục lưu hình ảnh tương đối
                var logicalPath = waterMark
                                      ? GetLogicalPath(imagePath, waterMark, fileName).Replace("/upload/", "/img/")
                                      : GetLogicalPath(imagePath, waterMark, fileName).Replace("/upload/", "/image/");

                //Đường dẫn tương đối của hình ảnh sau khi resize
                var logicalImagePath = logicalPath + fileNameScale + ImageExtension;

                //Đường dẫn tuyệt đối của hình ảnh sau khi resize
                var physicalImagePath = HttpContext.Current.Server.MapPath(logicalImagePath);
                //Kiểm tra hình ảnh có tồn tại hay chưa?
                if (File.Exists(physicalImagePath))
                    return StaticUrl + logicalImagePath;

                var imageSource = GetImageSource(imagePath, size);
                var thumbnail = waterMark ? AddWaterMark(imageSource, text) : imageSource;

                return StaticUrl + SaveImage(logicalPath, thumbnail, fileNameScale);
            }
            catch (Exception)
            {
                return String.Empty;
            }          
        }
        public static string SaveImage(string logicalPath, Image imageData, string imageName)
        {
            try
            {
                //Đường dẫn tuyệt đối của thư mục lưu hình ảnh
                var physicalPath = HttpContext.Current.Server.MapPath(logicalPath);
                CreateDirectory(physicalPath);

                //Lấy đường dẫn tuyệt đối của hình ảnh để lưu
                var physicalImagePath = physicalPath + imageName + ImageExtension;

                //Đường dẫn tương đối của hình ảnh để hiển thị cho người dùng xem
                var imageUrl = logicalPath + imageName + ImageExtension;

                // Prepare for a controlled-quality JPEG export
                var jpegCodec = GetEncoderInfo("image/jpeg");
                var jpegEncoder = Encoder.Quality;
                var jpegEncoderParameters = new EncoderParameters(1);
                var jpegEncoderQuality = new EncoderParameter(jpegEncoder, 100L /*jpegQuality*/);

                jpegEncoderParameters.Param[0] = jpegEncoderQuality;

                imageData.Save(physicalImagePath, jpegCodec, jpegEncoderParameters);

                return imageUrl;
            }
            catch (Exception)
            {
                return String.Empty;
            }
            
        }
        public static Image ScaleImage(Image image, int maxWidth)
        {
            var ratio = 1.0;
            if (maxWidth < image.Width)
                ratio = (double)maxWidth / image.Width;

            var newWidth = (int)(image.Width * ratio);
            var newHeight = (int)(image.Height * ratio);

            var newImage = new Bitmap(newWidth, newHeight);
            using (var g = Graphics.FromImage(newImage))
            {
                g.DrawImage(image, 0, 0, newWidth, newHeight);
            }
            return newImage;
        }
        public static string GetUniqueFileName()
        {
            return DateTime.Now.ToFileTimeUtc().ToString();
        }
        public static Image Base64ToImage(string base64String)
        {
            // Convert Base64 String to byte[]
            var imageBytes = Convert.FromBase64String(base64String);
            var ms = new MemoryStream(imageBytes, 0, imageBytes.Length);

            // Convert byte[] to Image
            ms.Write(imageBytes, 0, imageBytes.Length);
            var image = Image.FromStream(ms, true);
            return image;
        }

        private static string GetLogicalPath(string imagePath, bool waterMark, string fileName)
        {
            //Lấy đường dẫn tương đối của thư mục lưu hình ảnh
            var logicalPath = waterMark
                            ? imagePath.Replace("/upload/album/", "/upload/img/").Replace(fileName, "")
                            : imagePath.Replace("/upload/album/", "/upload/image/").Replace(fileName, "");
            var physicalPath = HttpContext.Current.Server.MapPath(logicalPath); //Đường dẫn tuyệt đối của thư mục lưu hình ảnh
            CreateDirectory(physicalPath);
            return logicalPath;
        }
        private static void CreateDirectory(string physicalPath)
        {
            if (!Directory.Exists(physicalPath))
                Directory.CreateDirectory(physicalPath);
        }
        private static Image AddWaterMark(Image image, string text)
        {
            //Get Image
            var g = Graphics.FromImage(image);

            //The InterpolationMode was the catalyst to eliminate pixelation.
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;

            //Watermark
            var imgLogo = Image.FromFile(HttpContext.Current.Server.MapPath(PathLogo));//Load water mark

            //Resize kích thước water mark theo tỉ lệ với ảnh gốc
            int w = imgLogo.Width, h = imgLogo.Height;
            if (imgLogo.Width > image.Width)
            {
                w = image.Width - 10;
                h = h * image.Width / imgLogo.Width;
            }

            //Draw lại water mark theo kích thước mới
            var transparentLogo = new Bitmap(w, h);
            using (var graphics = Graphics.FromImage(transparentLogo))
            {
                graphics.CompositingQuality = CompositingQuality.HighSpeed;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.CompositingMode = CompositingMode.SourceOver;
                graphics.DrawImage(imgLogo, 0, 0, w, h);
            }

            //Add water mark vào ảnh
            g.DrawImage(transparentLogo, image.Width - w - 5, image.Height - h - 20);

            //Add text vào ảnh
            var stringFormat = new StringFormat {Alignment = StringAlignment.Far};
            g.DrawString(text,
                new Font("Tahoma", 10, FontStyle.Bold),
                Brushes.OrangeRed,
                new PointF(image.Width - 5, image.Height - 20), stringFormat); 

            return image;
        }
        private static Image GetImageSource(string pathImage, int maxWidth)
        {
            Image thumbnail;
            if (pathImage.StartsWith("http://") || pathImage.StartsWith("https://"))
            {
                //Get image from URL
                Image source;
                var request = WebRequest.Create(pathImage);
                using (var response = request.GetResponse())
                using (var stream = response.GetResponseStream())
                    source = Image.FromStream(stream);
                var bmpPostedImage = new Bitmap(source);
                thumbnail = ScaleImage(bmpPostedImage, maxWidth);
            }
            else
            {
                //Get image from file
                thumbnail = ScaleImage(Image.FromFile(HttpContext.Current.Server.MapPath(pathImage)), maxWidth);
            }
            return thumbnail;
        }
        private static ImageCodecInfo GetEncoderInfo(string encoderString)
        {
            return ImageCodecInfo.GetImageEncoders().FirstOrDefault(info => info.MimeType == encoderString);
        }       
    }
}
